package com.iflytek.autofly.setting.biz.sound;

import android.content.Context;
import android.provider.Settings;

import com.iflytek.autofly.audioservice.aidl.Balance;
import com.iflytek.autofly.audioservice.util.AudioManager;
import com.iflytek.autofly.audioservice.util.AudioServiceCons;
import com.iflytek.autofly.audioservice.util.IAudioListener;
import com.iflytek.autofly.bluetoothservice.util.BluetoothServiceCons.AidlStatus;
import com.iflytek.autofly.setting.util.FlyPlatfromUtil;
import com.iflytek.autofly.setting.util.FlySettings;
import com.iflytek.autofly.utils.FlyLog;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class FlyAudioManager {

    private static final String TAG = "FlyAudioManager";
    private List<IFlyAudioListener> mListenerList = new ArrayList<>();
    private ReadWriteLock mListenerListLock = new ReentrantReadWriteLock(false);
    private volatile boolean mServiceReady = false;
    private IAudioListener mListener;
    private AudioManager mMngr;
    private Context mContext;
    private FlyAudioManager() {
    }

    public static FlyAudioManager registerListener(Context ctx,
                                                   IFlyAudioListener flyAudioListener) {
        FlyAudioManagerInstance.INST.init(ctx, flyAudioListener);
        return FlyAudioManagerInstance.INST;
    }

    public static void unregisterListener(IFlyAudioListener l) {
        FlyAudioManagerInstance.INST.fini(l);
    }

    public static void restoreDefault(Context applicationContext) {
        final CyclicBarrier barrier = new CyclicBarrier(2);
        IFlyAudioListener l = new IFlyAudioListener() {
            @Override
            public void onServiceConnected(boolean succeed) {
                try {
                    barrier.await();
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onTipVolumeChanged(int v) {
            }

            @Override
            public void onNaviVolumeChanged(int v) {
            }

            @Override
            public void onDefaultVolumeChanged(int value) {
            }

            @Override
            public void onMediaVolumeChanged(int v) {
            }

            @Override
            public void onLoudnessCompensationStateChanged(boolean enabled) {
            }

            @Override
            public void onEqChanged(int index, int value) {
            }

            @Override
            public void onEQModeChanged(int index) {
            }

            @Override
            public void onMixModeChanged(MixMode mode) {
            }

            @Override
            public void onInCallHintModeChanged(InCallHintMode mode) {
            }

            @Override
            public void onSpeedEnhanceModeChanged(boolean isOn) {
            }

            @Override
            public void onNoticeRingChanged(boolean isOn) {
            }

            @Override
            public void onKeyRingChanged(boolean isOn) {
            }

            @Override
            public void onMuteOnScreenOffChanged(boolean state) {
            }

            @Override
            public void onMuteOnReverse(boolean b) {
            }

            @Override
            public void onCallVolumeChanged(int v) {
            }

            @Override
            public void onBalaceChanged(int balance, int fade) {
            }
        };
        FlyAudioManager audio = FlyAudioManager.registerListener(
                applicationContext, l);

        try {
            barrier.await(1000, TimeUnit.MILLISECONDS);
            audio.setEQMode(0);
            audio.setBalance(0, 0);
            audio.setCallVolume(40 * audio.getMaxCallVolume() / 100);
            audio.setTipVolume(40 * audio.getMaxTipVolume() / 100);
            audio.setMediaVolume(40 * audio.getMaxMediaVolume() / 100);
            audio.enableLoudnessCompensation();

            FlyAudioManager.unregisterListener(l);
        } catch (InterruptedException | TimeoutException | BrokenBarrierException e) {
            e.printStackTrace();
        }

    }

    private void init(Context ctx, IFlyAudioListener l) {
        if (l == null) {
            FlyLog.e(TAG, "invalid arg IFlyAudioListener is null");
            return;
        }
        mContext = ctx;
        mListenerListLock.writeLock().lock();
        mListenerList.add(l);
        if (mServiceReady) {
            l.onServiceConnected(true);
        } else {
            if (mMngr == null) {
                mListener = new IAudioListener() {

                    @Override
                    public void onServiceStatusChanged(int status) {
                        if (status == AidlStatus.SERVICE_AIDL_BOUND) {
                            mListenerListLock.readLock().lock();
                            for (IFlyAudioListener ll : mListenerList) {
                                ll.onServiceConnected(true);
                            }
                            mListenerListLock.readLock().unlock();
                            mServiceReady = true;
                        } else if (status == AidlStatus.SERVICE_AIDL_NOT_BOUND) {
                            mListenerListLock.writeLock().lock();
                            mMngr = null;
                            mListenerListLock.writeLock().unlock();

                            mListenerListLock.readLock().lock();
                            for (IFlyAudioListener ll : mListenerList) {
                                ll.onServiceConnected(false);
                            }
                            mListenerListLock.readLock().unlock();
                            mServiceReady = false;
                        }
                    }

                    @Override
                    public void onLoudnessChanged(int i, int i1, int i2) {

                    }

                    @Override
                    public void onLoudnessCompensationChanged(boolean enabled) {
                        mListenerListLock.readLock().lock();
                        for (IFlyAudioListener ll : mListenerList) {
                            ll.onLoudnessCompensationStateChanged(enabled);
                        }
                        mListenerListLock.readLock().unlock();
                    }

                    @Override
                    public void onAudioChannel() {
                    }

                    @Override
                    public void onEqChanged(int index, int value) {
                        mListenerListLock.readLock().lock();
                        for (IFlyAudioListener ll : mListenerList) {
                            ll.onEqChanged(index, value);
                        }
                        mListenerListLock.readLock().unlock();
                    }

                    @Override
                    public void onMuteChanged(boolean isMute) {
                        FlyLog.d(TAG, "enter|mute=" + isMute);
                    }


                    @Override
                    public void onVolumeChanged(int channel, int level) {
                        switch (channel) {
                            case AudioServiceCons.AudioChannel.MEDIA:
                                mListenerListLock.readLock().lock();
                                for (IFlyAudioListener ll : mListenerList) {
                                    ll.onMediaVolumeChanged(level);
                                }
                                mListenerListLock.readLock().unlock();
                                break;
                            case AudioServiceCons.AudioChannel.BT_TEL:
                                mListenerListLock.readLock().lock();
                                for (IFlyAudioListener ll : mListenerList) {
                                    ll.onCallVolumeChanged(level);
                                }
                                mListenerListLock.readLock().unlock();
                                break;
                            case AudioServiceCons.AudioChannel.TIP:
                                mListenerListLock.readLock().lock();
                                for (IFlyAudioListener ll : mListenerList) {
                                    ll.onTipVolumeChanged(level);
                                }
                                mListenerListLock.readLock().unlock();
                                break;
                            case AudioServiceCons.AudioChannel.DEFAULT:
                                mListenerListLock.readLock().lock();
                                for (IFlyAudioListener ll : mListenerList) {
                                    ll.onDefaultVolumeChanged(level);
                                }
                                mListenerListLock.readLock().unlock();
                                break;
                            default:
                        }
                    }

                    @Override
                    public void onBalanceChanged(Balance balance) {
                        if (balance != null) {
                            mListenerListLock.readLock().lock();
                            for (IFlyAudioListener ll : mListenerList) {
                                ll.onBalaceChanged(balance.getBal(), balance.getFade());
                            }
                            mListenerListLock.readLock().unlock();
                        } else {
                            FlyLog.e(TAG, "balance is null");
                        }

                    }

                    @Override
                    public void onNaviMixScaleChanged(int v) {
                        mListenerListLock.readLock().lock();
                        for (IFlyAudioListener ll : mListenerList) {
                            // TODO
                        }
                        mListenerListLock.readLock().unlock();

                    }

                    @Override
                    public void onKeyToneChanged(boolean b) {
                        mListenerListLock.readLock().lock();
                        for (IFlyAudioListener ll : mListenerList) {
                            ll.onKeyRingChanged(b);
                        }
                        mListenerListLock.readLock().unlock();
                    }

                    @Override
                    public void onVolumeOnSpeedChanged(boolean b) {
                        mListenerListLock.readLock().lock();
                        for (IFlyAudioListener ll : mListenerList) {
                            ll.onSpeedEnhanceModeChanged(b);
                        }
                        mListenerListLock.readLock().unlock();
                    }

                    @Override
                    public void onNaviMixChanged(boolean b) {
                    }

                    @Override
                    public void onChannelGainChanged(int i, int i1) {
                    }

                    @Override
                    public void onScreenOffMuteChanged(boolean b) {
                        mListenerListLock.readLock().lock();
                        for (IFlyAudioListener ll : mListenerList) {
                            ll.onMuteOnScreenOffChanged(b);
                        }
                        mListenerListLock.readLock().unlock();
                    }

                    @Override
                    public void onReverseMuteChanged(boolean b) {
                        mListenerListLock.readLock().lock();
                        for (IFlyAudioListener ll : mListenerList) {
                            ll.onMuteOnReverse(b);
                        }
                        mListenerListLock.readLock().unlock();
                    }

                };
                mMngr = AudioManager.registerListener(ctx, mListener);
            }
        }
        mListenerListLock.writeLock().unlock();
    }

    private void fini(IFlyAudioListener l) {

        mListenerListLock.writeLock().lock();
        Iterator<IFlyAudioListener> it;
        for (it = mListenerList.iterator(); it.hasNext(); ) {
            IFlyAudioListener ll = it.next();
            if (ll == l) {
                it.remove();
            }
        }
        if (mListenerList.isEmpty()) {
            FlyLog.d(TAG, "real fini");
            AudioManager.unregisterListener(mListener);
            mMngr = null;
            mServiceReady = false;
        }

        mListenerListLock.writeLock().unlock();
    }

    public boolean isKeyRingEnabled() {
        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return false;
        }
        int ret = mMngr.getKeyToneEnableState();
        if (!FlyPlatfromUtil.isError(ret)) {
            return ret == 1;
        }
        FlyLog.e(TAG, "platform error: " + FlyPlatfromUtil.error(ret));
        return false;
    }

    public boolean isKeyRingValid() {
        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return false;
        }
        return mMngr.isKeyToneControlValid() == 0;
    }

    public void setKeyRing(boolean checked) {
        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return;
        }
        mMngr.setKeyToneEnable(checked);
    }

    public boolean isMediaVolumeValid() {
        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return false;
        }
        int ret = mMngr.isVolumeControlValid(AudioServiceCons.AudioChannel.MEDIA);
        if (!FlyPlatfromUtil.isError(ret)) {
            return ret == 1;
        }
        FlyLog.e("platform ret " + FlyPlatfromUtil.error(ret));
        return false;
    }

    public int getMaxMediaVolume() {
        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return 0;
        }
        int ret = mMngr.getMaxVolume(AudioServiceCons.AudioChannel.MEDIA);
        if (!FlyPlatfromUtil.isError(ret)) {
            return ret;
        }
        FlyLog.e("platform ret " + FlyPlatfromUtil.error(ret));
        return ret;
    }

    public int getMediaVolume() {
        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return 0;
        }
        int ret = mMngr.getVolume(AudioServiceCons.AudioChannel.MEDIA);
        if (!FlyPlatfromUtil.isError(ret)) {
            return ret;
        }
        FlyLog.e("platform ret " + FlyPlatfromUtil.error(ret));
        return ret;
    }

    public void setMediaVolume(int progress) {
        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return;
        }
        mMngr.setVolume(AudioServiceCons.AudioChannel.MEDIA, progress);
    }

    public boolean isCallVolumeValid() {
        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return false;
        }
        int ret = mMngr.isVolumeControlValid(AudioServiceCons.AudioChannel.BT_TEL);
        if (!FlyPlatfromUtil.isError(ret)) {
            return ret == 1;
        }
        FlyLog.e("platform ret " + FlyPlatfromUtil.error(ret));
        return false;
    }

    public int getMaxCallVolume() {
        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return 0;
        }
        if (mMngr == null) {
            FlyLog.e(TAG, "mngr is null");
            return 0;
        }
        int ret = mMngr.getMaxVolume(AudioServiceCons.AudioChannel.BT_TEL);
        if (!FlyPlatfromUtil.isError(ret)) {
            return ret;
        }
        FlyLog.e("platform ret " + FlyPlatfromUtil.error(ret));
        return ret;
    }

    public int getCallVolume() {
        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return 0;
        }
        int ret = mMngr.getVolume(AudioServiceCons.AudioChannel.BT_TEL);
        if (!FlyPlatfromUtil.isError(ret)) {
            return ret;
        }
        FlyLog.e("platform ret " + FlyPlatfromUtil.error(ret));
        return ret;
    }

    public void setCallVolume(int progress) {
        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return;
        }
        mMngr.setVolume(AudioServiceCons.AudioChannel.BT_TEL, progress);
    }

    public boolean isTipVolumeValid() {
        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return false;
        }
        int ret = mMngr.isVolumeControlValid(AudioServiceCons.AudioChannel.TIP);
        if (!FlyPlatfromUtil.isError(ret)) {
            return ret == 1;
        }
        FlyLog.e("platform ret " + FlyPlatfromUtil.error(ret));
        return false;
    }

    public int getMaxTipVolume() {
        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return 0;
        }
        int ret = mMngr.getMaxVolume(AudioServiceCons.AudioChannel.TIP);
        if (!FlyPlatfromUtil.isError(ret)) {
            return ret;
        }
        FlyLog.e("platform ret " + FlyPlatfromUtil.error(ret));
        return ret;
    }

    public int getTipVolume() {
        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return 0;
        }
        int ret = mMngr.getVolume(AudioServiceCons.AudioChannel.TIP);
        if (!FlyPlatfromUtil.isError(ret)) {
            return ret;
        }
        FlyLog.e("platform ret " + FlyPlatfromUtil.error(ret));
        return ret;
    }

    public void setTipVolume(int progress) {
        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return;
        }
        mMngr.setVolume(AudioServiceCons.AudioChannel.TIP, progress);
    }

    public void enableLoudnessCompensation() {
        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return;
        }
        mMngr.setLoudnessCompensationEnable(true);
    }

    public void disableLoudnessCompensation() {
        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return;
        }
        mMngr.setLoudnessCompensationEnable(false);
    }

    public boolean isLoudnessCompensationEnabled() {
        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return false;
        }
        int ret = mMngr.getLoudnessCompensationEnableState();
        if (!FlyPlatfromUtil.isError(ret)) {
            return ret == 1;
        }
        FlyLog.e("platform ret " + FlyPlatfromUtil.error(ret));
        return false;
    }

    public int getEQMode() {
        if (mMngr == null) {
            FlyLog.e(TAG, "service invalid");
            return 0;
        }
        int index = mMngr.getEQMode();

        FlyLog.d(TAG, "mode:" + index);
        return index;
    }

    public void setEQMode(int index) {
        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return;
        }
        mMngr.setEQMode(index);
        final int mode = mMngr.getEQMode();

        new Thread(new Runnable() {
            @Override
            public void run() {
                mListenerListLock.readLock().lock();
                for (IFlyAudioListener ll : mListenerList) {
                    ll.onEQModeChanged(mode);
                }
                mListenerListLock.readLock().unlock();
            }
        }).start();
    }

    public Balance getBalance() {
        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return null;
        }
        Balance bal = null;
        try {
            bal = mMngr.getBalance();
        }catch (Exception e){
            FlyLog.e(TAG, e);
        }
        if (bal == null) {
            FlyLog.e(TAG, "platform error ");
            return null;
        }
        return bal;
    }

    public void setBalance(int b, int f) {
        FlyLog.d(TAG, "balance=" + b + ",fade=" + f);
        Balance bal = new Balance();
        bal.setBal(b);
        bal.setFade(f);
        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return;
        }
        mMngr.setBalance(bal);
    }

    public int getBalanceMax() {
        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return 0;
        }
        Balance bal = mMngr.getBalanceMax();
        if (bal != null) {
            return bal.getBal();
        }
        FlyLog.e(TAG, "platform error");
        return 0;
    }

    public int getBalanceMin() {
        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return 0;
        }
        Balance bal = mMngr.getBalanceMin();
        if (bal != null) {
            return bal.getBal();
        }
        FlyLog.e(TAG, "platform error");
        return 0;
    }

    public void setEQ(int index, int value) {
        FlyLog.d(TAG, "index:" + index + ",value=" + value);
        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return;
        }
        mMngr.setEQ(index, value);
    }

    public int getEQBandCount() {

        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return 0;
        }
        return mMngr.getEQBandCount();
    }

    public int getEQMinVal() {
        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return 0;
        }
        return mMngr.getEQMinVal();
    }

    public int getEQMaxVal() {
        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return 0;
        }
        return mMngr.getEQMaxVal();
    }


    public int getEQ(int i) {
        if (mMngr != null) {
            return mMngr.getEQ(i);
        }
        return 0;
    }

    public void getEQ() {
        if (mMngr == null) {
            return;
        }

        final int bandCount = getEQBandCount();
        if (bandCount <= 0) {
            return;
        }
        int[] values = new int[bandCount];

        for (int i = 0; i < bandCount; i++) {
            values[i] = mMngr.getEQ(i);
            FlyLog.d(TAG, "band:" + i + " value:" + values[i]);
        }

        final int[] values_ = values;
        new Thread(new Runnable() {

            @Override
            public void run() {
                mListenerListLock.readLock().lock();
                for (IFlyAudioListener ll : mListenerList) {
                    for (int i = 0; i < bandCount; i++) {
                        ll.onEqChanged(i, values_[i]);
                    }
                }
                mListenerListLock.readLock().unlock();
            }
        }).start();
    }

    public List<String> getEQBandNames() {
        if (mMngr == null) {
            return null;
        }
        return mMngr.getEQBandNames();
    }

    public int getMaxDefaultVolume() {
        if (mMngr == null) {
            return -1;
        }
        int ret = mMngr.getMaxVolume(AudioServiceCons.AudioChannel.DEFAULT);
        if (!FlyPlatfromUtil.isError(ret)) {
            return ret;
        }
        FlyLog.e(TAG, "platform error:" + FlyPlatfromUtil.error(ret));
        return -1;
    }

    public int getDefaultVolume() {
        if (mMngr == null) {
            return -1;
        }
        int ret = mMngr.getVolume(AudioServiceCons.AudioChannel.DEFAULT);
        if (!FlyPlatfromUtil.isError(ret)) {
            return ret;
        }
        FlyLog.e(TAG, "platform error:" + FlyPlatfromUtil.error(ret));
        return -1;
    }

    public void setDefaultVolume(int v) {
        if (mMngr == null) {
            return;
        }
        mMngr.setVolume(AudioServiceCons.AudioChannel.DEFAULT, v);
    }

    public int getNaviVolume() {
        if (mMngr == null) {
            return -1;
        }
        int ret = mMngr.getVolume(AudioServiceCons.AudioChannel.NAV);
        if (!FlyPlatfromUtil.isError(ret)) {
            return ret;
        }
        FlyLog.e(TAG, "platform error:" + FlyPlatfromUtil.error(ret));
        return -1;
    }

    public void setNaviVolume(int v) {
        if (mMngr == null) {
            return;
        }
        mMngr.setVolume(AudioServiceCons.AudioChannel.NAV, v);
    }

    public int getMaxNaviVolume() {
        if (mMngr == null) {
            return -1;
        }
        int ret = mMngr.getMaxVolume(AudioServiceCons.AudioChannel.NAV);
        if (!FlyPlatfromUtil.isError(ret)) {
            return ret;
        }
        FlyLog.e(TAG, "platform error:" + FlyPlatfromUtil.error(ret));
        return -1;
    }

    public void setInCallHintMode(InCallHintMode inCallHintModeSys) {
        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return;
        }
        boolean enable = false;
        switch (inCallHintModeSys) {
            case TTS:
                enable = false;
                break;
            case SYS:
                enable = true;
                break;
        }
        mMngr.setSystemCallRingEnable(enable);
    }

    public InCallHintMode getIncomingCallHintMode() {
        if (mMngr == null) {
            FlyLog.e(TAG, "mMngr is null");
            return InCallHintMode.SYS;
        }
        int result = mMngr.getSystemCallRingEnableState();
        if (result < 0) {
            FlyLog.e(TAG, "result: " + result);
            return InCallHintMode.SYS;
        }
        InCallHintMode mode = InCallHintMode.SYS;
        switch (result) {
            case 1:
                mode = InCallHintMode.SYS;
                break;
            case 0:
                mode = InCallHintMode.TTS;
                break;
            default:
                FlyLog.e(TAG, "result is not in range");
                break;
        }
        return mode;
    }

    public void turnOnMix() {
        if (mMngr != null) {
            mMngr.setNaviMixEnable(true);
        }
    }

    public void turnOffMix() {
        if (mMngr != null) {
            mMngr.setNaviMixEnable(false);
        }
    }

    public boolean getMixState() {
        if (mMngr == null) {
            return false;
        }

        int ret = mMngr.getNaviMixEnableState();
        if (!FlyPlatfromUtil.isError(ret)) {
            return ret == 1;
        }
        FlyLog.e(TAG, "platform error:" + FlyPlatfromUtil.error(ret));
        return false;
    }

    public boolean isSpeedEnhanceOn() {
        if (mMngr == null) {
            return Settings.Global.getInt(mContext.getContentResolver(), FlySettings.Sound.SPEED_ENHANCE, 1) == 1;
        }
        int ret = mMngr.getVolumeOnSpeedEnableState();
        if (!FlyPlatfromUtil.isError(ret)) {
            return ret == 1;
        }
        FlyLog.e(TAG, "platform error:" + FlyPlatfromUtil.error(ret));
        return Settings.Global.getInt(mContext.getContentResolver(), FlySettings.Sound.SPEED_ENHANCE, 1) == 1;
    }

    public void turnOnSpeedEnhance() {
        FlyLog.d(TAG, "enter");
        if (mMngr != null) {
            mMngr.setVolumeOnSpeedEnable(true);
            Settings.Global.putInt(mContext.getContentResolver(), FlySettings.Sound.SPEED_ENHANCE, 1);
        }
    }

    public void turnOffSpeedEnhance() {
        FlyLog.d(TAG, "enter");
        if (mMngr != null) {
            mMngr.setVolumeOnSpeedEnable(false);
            Settings.Global.putInt(mContext.getContentResolver(), FlySettings.Sound.SPEED_ENHANCE, 0);
        }
    }

    public void enableMuteOnScreenOff() {
        FlyLog.d(TAG, "enter");
        if (mMngr != null) {
            mMngr.setOffScreenMuteEnable(true);
            Settings.Global.putInt(mContext.getContentResolver(), FlySettings.Sound.MUTE_SCREEN_OFF, 1);
        }
    }

    public void disableMuteOnScreenOff() {
        FlyLog.d(TAG, "enter");
        if (mMngr != null) {
            mMngr.setOffScreenMuteEnable(false);
            Settings.Global.putInt(mContext.getContentResolver(), FlySettings.Sound.MUTE_SCREEN_OFF, 0);
        }

    }

    public boolean isMuteOnScreenOff() {
        if (mMngr == null) {
            return Settings.Global.getInt(mContext.getContentResolver(), FlySettings.Sound.MUTE_SCREEN_OFF, 1) == 1;
        }
        int ret = mMngr.getOffScreenMuteEnableState();
        if (!FlyPlatfromUtil.isError(ret)) {
            return ret == 1;
        }
        FlyLog.e(TAG, "platform error:" + FlyPlatfromUtil.error(ret));
        return Settings.Global.getInt(mContext.getContentResolver(), FlySettings.Sound.MUTE_SCREEN_OFF, 1) == 1;
    }

    public void enableMuteOnReverse() {
        FlyLog.d(TAG, "enter");
        if (mMngr != null) {
            mMngr.setReverseMuteEnable(true);
            Settings.Global.putInt(mContext.getContentResolver(), FlySettings.Sound.MUTE_REVERSE, 1);
        }
    }

    public void disableMuteOnReverse() {
        FlyLog.d(TAG, "enter");
        if (mMngr != null) {
            mMngr.setReverseMuteEnable(false);
            Settings.Global.putInt(mContext.getContentResolver(), FlySettings.Sound.MUTE_REVERSE, 0);
        }

    }

    public boolean isMuteOnReverse() {
        if (mMngr == null) {
            return Settings.Global.getInt(mContext.getContentResolver(), FlySettings.Sound.MUTE_REVERSE, 0) == 1;
        }
        int ret = mMngr.getReverseMuteEnableState();
        if (!FlyPlatfromUtil.isError(ret)) {
            return ret == 1;
        }
        FlyLog.e(TAG, "platform error:" + FlyPlatfromUtil.error(ret));
        return Settings.Global.getInt(mContext.getContentResolver(), FlySettings.Sound.MUTE_REVERSE, 0) == 1;
    }


    public MixMode getMixMode() {
        if (mMngr == null) {
            FlyLog.e(TAG, "mngr not ready");
            return MixMode.NAVI_FIRST;
        }
        int ret = mMngr.getNaviMixScale();
        FlyLog.d(TAG, "getNaviMixScale:" + ret);
        if (!FlyPlatfromUtil.isError(ret)) {
            if (ret == 0) {
                return MixMode.NORMAL;
            }
            return MixMode.NAVI_FIRST;
        }
        FlyLog.e(TAG, "platform error:" + FlyPlatfromUtil.error(ret));
        return MixMode.NAVI_FIRST;
    }

    public void setMixMode(MixMode mode) {
        if (mMngr == null) {
            FlyLog.e(TAG, "mngr not ready");
            return;
        }
        FlyLog.d(TAG, "mode:" + mode);
        switch (mode) {
            case NAVI_FIRST:
                mMngr.setNaviMixScale(6);
                break;
            case NORMAL:
                mMngr.setNaviMixScale(0);
                break;
        }
    }

    public void mute() {
        FlyLog.d(TAG, "enter");
        if (mMngr == null) {
            FlyLog.e(TAG, "invalid mngr");
            return;
        }
        mMngr.setMuteEnable(true);
    }

    public void unMute() {
        FlyLog.d(TAG, "enter");
        if (mMngr == null) {
            FlyLog.e(TAG, "invalid mngr");
            return;
        }
        mMngr.setMuteEnable(false);
    }

    public boolean getMuteState() {
        FlyLog.d(TAG, "enter");
        if (mMngr == null) {
            FlyLog.e(TAG, "invalid mngr");
            return false;
        }
        return mMngr.getMuteEnableState() == 1;
    }

    public enum MixMode {
        NAVI_FIRST,
        NORMAL;

        @Override
        public String toString() {
            switch (this) {
                case NAVI_FIRST:
                    return "NAVI_FIRST";
                case NORMAL:
                    return "NORMAL";
            }
            return super.toString();
        }
    }

    public enum InCallHintMode {
        TTS,
        SYS
    }

    public interface IFlyAudioListener {
        void onServiceConnected(boolean succeed);

        void onMediaVolumeChanged(int v);

        void onCallVolumeChanged(int v);

        void onTipVolumeChanged(int v);

        void onNaviVolumeChanged(int v);

        void onDefaultVolumeChanged(int value);

        void onLoudnessCompensationStateChanged(boolean enabled);

        void onEqChanged(int index, int value);

        void onBalaceChanged(int balance, int fade);

        void onEQModeChanged(int index);

        void onMixModeChanged(MixMode mode);

        void onInCallHintModeChanged(InCallHintMode mode);

        void onSpeedEnhanceModeChanged(boolean isOn);

        void onNoticeRingChanged(boolean isOn);

        void onKeyRingChanged(boolean isOn);

        void onMuteOnScreenOffChanged(boolean state);

        void onMuteOnReverse(boolean b);
    }

    private static class FlyAudioManagerInstance {
        static FlyAudioManager INST = new FlyAudioManager();
    }
}
